<?php
namespace adminmatrix\admin\command\event;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\Table;
use adminmatrix\admin\listen\Listen;

class Lists extends Command
{
    protected function configure()
    {
        $this->setName('event:list')
            ->setDescription('显示事件列表')
            ->addOption('type', 't', \think\console\input\Option::VALUE_OPTIONAL, '类型：event、listener、subscribe或annotation', '')
            ->addOption('group', 'g', \think\console\input\Option::VALUE_NONE, '按分组显示')
            ->addOption('relation', 'r', \think\console\input\Option::VALUE_NONE, '显示事件监听关系')
            ->addOption('detail', 'd', \think\console\input\Option::VALUE_NONE, '显示详细信息');
    }

    protected function execute(Input $input, Output $output)
    {
        $output->writeln('事件列表');
        
        // 获取选项
        $type = $input->getOption('type');
        $byGroup = $input->getOption('group');
        $showRelation = $input->getOption('relation');
        $showDetail = $input->getOption('detail');
        
        // 使用Listen类获取事件和监听器列表
        $listen = new Listen($this->app);
        
        if ($byGroup) {
            // 按分组显示
            $data = $listen->getByGroup($type);
            $this->displayGroupedData($output, $data, $type, $showDetail);
        } else {
            // 不分组显示
            $data = $listen->get($type);
            $this->displayData($output, $data, $type, $showDetail);
        }
        
        // 显示已注册的事件监听关系
        if ($showRelation) {
            $output->writeln('');
            $output->writeln('已注册的事件监听关系:');
            $registeredEvents = $listen->getRegisteredEvents();
            $this->displayRegisteredEvents($output, $registeredEvents);
        }
    }
    
    /**
     * 显示事件和监听器数据
     * @param Output $output 输出对象
     * @param array $data 数据
     * @param string $type 类型
     * @param bool $showDetail 是否显示详细信息
     */
    protected function displayData(Output $output, array $data, string $type, bool $showDetail = false): void
    {
        $table = new Table();
        $table->setHeader(['类型', '名称', '分组', '标题', '类']);
        
        // 合并所有类型的数据
        $allItems = [];
        
        if ($type === 'event' || $type === '') {
            $events = $type === 'event' ? $data : $data['event'];
            foreach ($events as $event) {
                $allItems[] = array_merge(['type' => 'event'], $event);
            }
        }
        
        if ($type === 'listener' || $type === '') {
            $listeners = $type === 'listener' ? $data : $data['listener'];
            foreach ($listeners as $listener) {
                $allItems[] = array_merge(['type' => 'listener'], $listener);
            }
        }
        
        if ($type === 'subscribe' || $type === '') {
            $subscribes = $type === 'subscribe' ? $data : ($data['subscribe'] ?? []);
            foreach ($subscribes as $subscribe) {
                $allItems[] = array_merge(['type' => 'subscribe'], $subscribe);
            }
        }
        
        if ($type === 'annotation' || $type === '') {
            $annotations = $type === 'annotation' ? $data : ($data['annotation'] ?? []);
            foreach ($annotations as $annotation) {
                // 注解事件可能有不同的结构
                $item = [
                    'type' => 'annotation',
                    'name' => $annotation['name'],
                    'group' => $annotation['type'] ?? 'Annotation',
                    'title' => $annotation['title'],
                    'class' => $annotation['class'] . ($annotation['method'] ? '@' . $annotation['method'] : '')
                ];
                $allItems[] = $item;
            }
        }
        
        // 按名称排序
        usort($allItems, function($a, $b) {
            return $a['name'] <=> $b['name'];
        });
        
        // 添加到表格
        foreach ($allItems as $item) {
            $table->addRow([
                $item['type'],
                $item['name'],
                $item['group'],
                $item['title'],
                $item['class']
            ]);
        }
        
        $output->writeln($table->render());
        
        // 如果是订阅者类型且需要显示详细信息，显示订阅者方法
        if (($type === 'subscribe' || $type === '') && $showDetail) {
            $this->displaySubscriberMethods($output, $type === 'subscribe' ? $data : ($data['subscribe'] ?? []));
        }
    }
    
    /**
     * 显示分组的事件和监听器数据
     * @param Output $output 输出对象
     * @param array $data 数据
     * @param string $type 类型
     * @param bool $showDetail 是否显示详细信息
     */
    protected function displayGroupedData(Output $output, array $data, string $type, bool $showDetail = false): void
    {
        // 合并所有分组
        $allGroups = [];
        
        if ($type === 'event' || $type === '') {
            $eventGroups = $type === 'event' ? $data : ($data['event'] ?? []);
            foreach ($eventGroups as $group => $events) {
                if (!isset($allGroups[$group])) {
                    $allGroups[$group] = [];
                }
                
                foreach ($events as $event) {
                    $allGroups[$group][] = array_merge(['type' => 'event'], $event);
                }
            }
        }
        
        if ($type === 'listener' || $type === '') {
            $listenerGroups = $type === 'listener' ? $data : ($data['listener'] ?? []);
            foreach ($listenerGroups as $group => $listeners) {
                if (!isset($allGroups[$group])) {
                    $allGroups[$group] = [];
                }
                
                foreach ($listeners as $listener) {
                    $allGroups[$group][] = array_merge(['type' => 'listener'], $listener);
                }
            }
        }
        
        if ($type === 'subscribe' || $type === '') {
            $subscribeGroups = $type === 'subscribe' ? $data : ($data['subscribe'] ?? []);
            foreach ($subscribeGroups as $group => $subscribes) {
                if (!isset($allGroups[$group])) {
                    $allGroups[$group] = [];
                }
                
                foreach ($subscribes as $subscribe) {
                    $allGroups[$group][] = array_merge(['type' => 'subscribe'], $subscribe);
                }
            }
        }
        
        if ($type === 'annotation' || $type === '') {
            $annotationGroups = $type === 'annotation' ? $data : ($data['annotation'] ?? []);
            foreach ($annotationGroups as $group => $annotations) {
                if (!isset($allGroups[$group])) {
                    $allGroups[$group] = [];
                }
                
                foreach ($annotations as $annotation) {
                    // 注解事件可能有不同的结构
                    $item = [
                        'type' => 'annotation',
                        'name' => $annotation['name'],
                        'title' => $annotation['title'],
                        'class' => $annotation['class'] . ($annotation['method'] ? '@' . $annotation['method'] : '')
                    ];
                    $allGroups[$group][] = $item;
                }
            }
        }
        
        // 按分组显示
        foreach ($allGroups as $group => $items) {
            $output->writeln('');
            $output->writeln("分组: {$group} (" . count($items) . "个项目)");
            
            $table = new Table();
            $table->setHeader(['类型', '名称', '标题', '类']);
            
            // 按名称排序
            usort($items, function($a, $b) {
                return $a['name'] <=> $b['name'];
            });
            
            foreach ($items as $item) {
                $table->addRow([
                    $item['type'],
                    $item['name'],
                    $item['title'],
                    $item['class']
                ]);
            }
            
            $output->writeln($table->render());
            
            // 如果是订阅者类型且需要显示详细信息，为当前分组显示订阅者方法
            if (($type === 'subscribe' || $type === '') && $showDetail) {
                $groupSubscribers = array_filter($items, function($item) {
                    return $item['type'] === 'subscribe';
                });
                
                if (!empty($groupSubscribers)) {
                    $this->displaySubscriberMethods($output, $groupSubscribers);
                }
            }
        }
    }
    
    /**
     * 显示订阅者方法
     * @param Output $output 输出对象
     * @param array $subscribers 订阅者数据
     */
    protected function displaySubscriberMethods(Output $output, array $subscribers): void
    {
        // 添加调试信息
        $output->writeln('');
        $output->writeln('<info>订阅者方法信息调试:</info>');
        $output->writeln('订阅者数量: ' . count($subscribers));
        
        // 检查每个订阅者的方法信息
        foreach ($subscribers as $index => $subscriber) {
            $output->writeln('');
            $output->writeln("订阅者 #{$index}: {$subscriber['name']} (类: {$subscriber['class']})");
            
            if (!isset($subscriber['methods'])) {
                $output->writeln('<comment>  未找到方法信息</comment>');
                continue;
            }
            
            $methodCount = count($subscriber['methods']);
            $output->writeln("  方法数量: {$methodCount}");
            
            if ($methodCount > 0) {
                $table = new Table();
                $table->setHeader(['方法名', '标题', '参数数量']);
                
                foreach ($subscriber['methods'] as $method) {
                    $table->addRow([
                        $method['name'],
                        $method['title'],
                        $method['parameters']
                    ]);
                }
                
                $output->writeln($table->render());
            }
        }
    }
    
    /**
     * 显示已注册的事件监听关系
     * @param Output $output 输出对象
     * @param array $events 事件数据
     */
    protected function displayRegisteredEvents(Output $output, array $events): void
    {
        $table = new Table();
        $table->setHeader(['事件名称', '监听器数量', '监听器列表']);
        
        foreach ($events as $event => $listeners) {
            if (is_array($listeners)) {
                $listenersCount = count($listeners);
                $listenersStr = '';
                foreach ($listeners as $index => $listener) {
                    if (is_string($listener)) {
                        $listenersStr .= ($index + 1) . '. ' . $listener . PHP_EOL;
                    } elseif (is_object($listener) && method_exists($listener, '__toString')) {
                        $listenersStr .= ($index + 1) . '. ' . (string)$listener . PHP_EOL;
                    } elseif (is_array($listener) && count($listener) === 2) {
                        // 处理回调形式的监听器 [类, 方法]
                        if (is_object($listener[0])) {
                            $className = get_class($listener[0]);
                        } else {
                            $className = (string)$listener[0];
                        }
                        $listenersStr .= ($index + 1) . '. ' . $className . '@' . $listener[1] . PHP_EOL;
                    } else {
                        $listenersStr .= ($index + 1) . '. ' . gettype($listener) . PHP_EOL;
                    }
                }
                $table->addRow([$event, $listenersCount, $listenersStr]);
            }
        }
        
        $output->writeln($table->render());
    }
}
